package fr.emse.tatiana.filter;


import java.io.*;

import org.eclipse.core.resources.*;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;

import com.qizx.api.CompilationException;
import com.qizx.api.DataModelException;
import com.qizx.api.EvaluationException;
import com.qizx.api.EvaluationStackTrace;
import com.qizx.api.Expression;
import com.qizx.api.Item;
import com.qizx.api.ItemSequence;
import com.qizx.api.QName;
import com.qizx.api.QizxException;
import com.qizx.api.XQuerySession;
import com.qizx.api.XQuerySessionManager;
import com.qizx.api.util.XMLSerializer;
import com.qizx.util.basic.FileUtil;

import fr.emse.tatiana.TatianaConstants;

import net.axyana.qizxopen.clapp.XQuestCLI;


public class XQueryOut {

	public static String rootpath = ""; // don't use

	private static String[] makeStringArgs(Object[] args) {
		String[] ret = new String[args.length];
		for (int i=0;i<args.length; i++) {
			if (args[i] instanceof XQueryOut) {
				ret[i] = ((XQueryOut) args[i]).getName();
			} else if (args[i] instanceof String) {
				ret[i] = (String) args[i];
			} else {
				System.out.println("Invalid XQuery TaskFlow");
			}
		}
		return ret;
	}

	private XQuestCLI app;
	private String outfile;

	/**
	 * should be equivalent to java -jar qizxopen -q xqueryfile -- xqueryargs | java CleanUpXQueryOutput
	 * 
	 * @param xqueryfile
	 * @param xqueryargs
	 * @param outfile
	 * @throws FileNotFoundException 
	 */
	public XQueryOut(String xqueryfile, String[] xqueryargs, String outfile) {
		this(xqueryfile, xqueryargs, outfile, "");
	}
	
	public XQueryOut(String xqueryfile, String[] xqueryargs, String outfile, String docbase) {
		this.outfile=outfile;
		app = new XQuestCLI();

		app.output = outfile;

		app.appArgs = xqueryargs;
		IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(TatianaConstants.TATIANA_PROJECT_NAME);
		app.modBase = project.getFolder(TatianaConstants.SCRIPTS_FOLDER_NAME).getLocation().toString();
		app.docBase = docbase;
		app.queryFile = new String[1];
		app.queryFile[0]= new File(xqueryfile).getAbsolutePath();
		System.err.println("queryFile is set to "+app.queryFile[0]);
		app.shutdown = false;
			try {
				app.start();
			} catch (Exception e) {
				MessageDialog.openError(Display.getCurrent().getActiveShell(), "Problem running script", "There was an error while running script" + xqueryfile + " because of:\n" + e.getMessage());
				e.printStackTrace();
			}
	}
	
	// for when qizx2.0 works -- not adjusted to eclipse system
	public XQueryOut(String xqueryfile, String[] xqueryargs, String outfile, XQueryOut future) throws FileNotFoundException {

		this.outfile=outfile;
		Reader input = new FileReader(rootpath+"scripts/"+xqueryfile+".xq");

		XQuerySessionManager qman =
			new XQuerySessionManager(FileUtil.fileToURL("./scripts"));
		qman.setModuleResolver(new TatianaModuleResolver(FileUtil.fileToURL("./scripts")));
		XQuerySession session = qman.createSession();
		PrintWriter stderr = new PrintWriter(System.err, true);

		try {
			String src = FileUtil.loadString(input);
			Expression query = session.compileExpression(src);
			QName argVar = session.getQName("arguments");
			query.getContext().declareVariable(argVar, null);
			query.bindVariable(argVar, xqueryargs, null);

			XMLSerializer out = new XMLSerializer();
			out.setIndent(2);
			out.setOutput(new FileOutputStream(outfile),
					out.getEncoding());
			stderr = new PrintWriter(System.err, true);

			long T1, T0 = System.currentTimeMillis();

			// Pure evaluation, without retrieving results (returns an
			// iterator).
			// Due to lazy evaluation, this is sometimes much shorter
			// than the actual retrieval.
			ItemSequence v = query.evaluate();

			T1 = System.currentTimeMillis();
			int itemCount = 0;

			for (; v.moveToNextItem(); itemCount++)
			{
				Item item = v.getCurrentItem();

				if (item.isNode()) {
					v.export(out);
				}
				else {
					if (itemCount > 0)
						out.putText(" "); // some space
						out.putAtomText(v.getString());
				}
			}


			out.flush();

			stderr.println("-> " + itemCount + " item(s)");
			long T2 = System.currentTimeMillis();
			stderr.println("evaluation time: " + (T1 - T0)
					+ " ms, display time: " + (T2 - T1)
					+ " ms");


		} catch (IOException e1) {
			// TODO z much later Auto-generated catch block
			e1.printStackTrace();
		} catch (CompilationException e) {
			// TODO z much later Auto-generated catch block
			e.printStackTrace();
		} catch (EvaluationException e) {
			QName errCode = e.getErrorCode();
			stderr.println("*** execution error "
					+ (errCode != null? errCode.getLocalPart() : "<unknown code>")
					+ ": " + e.getMessage());
			if (e.getCause() != null) {
				stderr.println("  caused by: " + e.getCause());
			}
			PrintWriter err = new PrintWriter(System.err, true);
			EvaluationStackTrace[] stack = e.getStack();
			for (int i = 0; i < stack.length; ++i) {
				stack[i].print(err);
			}
			//e.printStackTrace();
		} catch (DataModelException e) {
			// TODO z much later Auto-generated catch block
			e.printStackTrace();
		} catch (QizxException e) {
			// TODO z much later Auto-generated catch block
			e.printStackTrace();
		}


		try {
			input.close();
		} catch (IOException e) {
			// TODO z much later Auto-generated catch block
			e.printStackTrace();
		}
	}


	public XQueryOut(String xqueryfile, Object[] xqueryargs, String outfile) throws FileNotFoundException {
		this(xqueryfile, makeStringArgs(xqueryargs), outfile);
	}

	public XQueryOut(String xqueryfile, Object xqueryarg, String outfile) throws FileNotFoundException {
		this(xqueryfile, new Object[]{xqueryarg}, outfile);
	}

	public XQueryOut(String xqueryfile, Object xqueryarg1, Object xqueryarg2, String outfile) throws FileNotFoundException {
		this(xqueryfile, new Object[]{xqueryarg1,xqueryarg2}, outfile);
	}



	public XQueryOut(String xqueryfile, Object xqueryarg1, Object xqueryarg2, Object xqueryarg3, Object xqueryarg4, String outfile) throws FileNotFoundException {
		this(xqueryfile, new Object[]{xqueryarg1,xqueryarg2, xqueryarg3, xqueryarg4}, outfile);
	}

	public XQueryOut(String xqueryfile, Object xqueryarg1, Object xqueryarg2, Object xqueryarg3, Object xqueryarg4, String xqueryarg5, String outfile) throws FileNotFoundException {
		this(xqueryfile, new Object[]{xqueryarg1,xqueryarg2, xqueryarg3, xqueryarg4, xqueryarg5}, outfile);
	}

	public String getName() {
		return outfile;
	}

	public void dispose() {
		TempFileFactory.dispose();	
	}

}
